package com.analyse.stock.utils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.ChineseDate;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.analyse.stock.enums.HolidayEnum;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.function.Function;

@Slf4j
public class PublicHolidayUtil {

    public static final Map<String,Set<String>> holidayMap = new HashMap<>();

    /**
     * 获取假期时间
     * @param holidayEnum 假期名称
     * @param year 当前年份
     * @return
     */
    public static Date getHoliday(HolidayEnum holidayEnum, int year) {
        switch (holidayEnum.getCode()) {
            case "NEWYEARDAY":
                return DateUtil.parse(year + "-1-1");
            case "CHINESENEWYEARGREGORIANFESTIVAL":
                ChineseDate chinesenewYearFestival = new ChineseDate(year, 1, 1);
                Date begin = chinesenewYearFestival.getGregorianDate();
                return DateUtil.offsetDay(begin,-1);
            case "QINGMINGFESTIVAL":
                int param = year - 2000;
                int qingmingDay = (int) (param * 0.2422 + 4.81) - param / 4;
                return DateUtil.parse(year + "-4-" + qingmingDay);
            case "LABORDAY":
                return DateUtil.parse(year + "-5-1");
            case "DRAGONBOATGREGORIANFESTIVAL":
                ChineseDate dragonBoatFestival = new ChineseDate(year, 5, 5);
                return dragonBoatFestival.getGregorianDate();
            case "MIDAUTUMNGREGORIANFESTIVAL":
                ChineseDate midAutumnFestival = new ChineseDate(year, 8, 15);
                return midAutumnFestival.getGregorianDate();
            case "NATIONALDAY":
                return DateUtil.parse(year + "-10-1");
            default:
                return new Date();
        }
    }

    public static boolean isTradingTime(Date date, Function<LocalTime,Boolean> function) {
        // 转换为java.time.ZoneDateTime
        // 使用系统默认时区
        ZonedDateTime zonedDateTime = date.toInstant().atZone(ZoneId.systemDefault());
        // 从ZonedDateTime获取LocalTime
        LocalTime localTime = zonedDateTime.toLocalTime();
        return function.apply(localTime);
    }
    public static boolean isWeekend(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
        return dayOfWeek == Calendar.SUNDAY || dayOfWeek == Calendar.SATURDAY;
    }

    public static boolean isTradingDate(String exchangeCode,Date date) {
        boolean week = isWeekend(date);
        if(week){
            log.info("## 今天是周末：{}",date.toString());
            return false;
        }
        int year = DateUtil.year(new Date());
        String key = String.format("%s_%s",exchangeCode,year);
        Set<String> dateList = Sets.newHashSet();
        if(holidayMap.containsKey(key) && CollUtil.isNotEmpty(holidayMap.get(key))){
            dateList = holidayMap.get(key);
        }else{
            for(HolidayEnum holidayEnum : HolidayEnum.values()){
                Date beginHoliday = getHoliday(holidayEnum, year);
                for(int i=0;i<holidayEnum.getDay();i++){
                    dateList.add(DateUtil.format(DateUtil.offsetDay(beginHoliday,i),DatePattern.NORM_DATE_FORMAT));
                }
            }
            holidayMap.put(key,dateList);
        }
        String currentDate = DateUtil.formatDate(date);
        if(dateList.contains(currentDate)){
            log.info("## 今天是假期：{}",currentDate);
            return false;
        }
        return true;
    }
    public static boolean isTradingDateTime(String exchangeCode,Date date, Function<LocalTime,Boolean> tradingTimeFun) {
        boolean isTradingDateBool = isTradingDate(exchangeCode,date);
        if(isTradingDateBool && Objects.nonNull(tradingTimeFun)){
            return isTradingTime(date,tradingTimeFun);
        }
        return isTradingDateBool;
    }
}
